import Utils from '../utils/index';
import Http from '../utils/Http';
import Config from '../config';
import OperationParser from './OperationParser';

// 定时器相关操作
class GanttTimer {
   constructor(Gantt) {
      this.Gantt = Gantt;
      this.intervals = {};
      this.timeouts = {};
   }

   // 启动 interval
   addInterval(name, interval, func) {
      this.clearInterval(name);
      this.intervals[name] = setInterval(func, interval);
   }

   // 清除 interval
   clearInterval(name) {
      if (name && this.intervals[name]) {
         clearInterval(this.intervals[name]);
         delete this.intervals[name];
      }
   }

   // 启动 timeout
   addTimeout(name, interval, func) {
      if (this.timeouts[name]) {
         clearTimeout(this.timeouts[name]);
      }

      this.timeouts[name] = setTimeout(func, interval);
   }

   // 清除 timeout
   clearTimeout(name) {
      if (name && this.timeouts[name]) {
         this.clearTimeout(this.timeouts[name]);
         delete this.timeouts[name];
      }
   }

   // 清除所有 interval 或  timeout
   clearAll(type) {
      let objects = null,
         method = null,
         key = null;
      if (type === 'timer') {
         objects = this.intervals;
         method = 'clearInterval';
      } else {
         objects = this.timeouts;
         method = 'clearTimeout';
      }

      for (key in objects) {
         window[method](objects[key]);
      }

      objects = {};
   }

   /*********************** 业务相关 ***********************/

   resetRefreshDataTimer() {
      this.clearInterval('updateData');
      if (this.Gantt.modal.dataUpdatedModal) {
         this.Gantt.modal.dataUpdatedModal.show(true);
      }
      this.refreshDataTimer();
   }

   // 定时刷新数据
   refreshDataTimer() {
      this.addInterval('updateData', Utils.timeUnit.minutes * 3, () => {
         this.Gantt.header.renderIron();
         // 刷新操作数据
         let postData = {
            ranges: this.Gantt.timeRange.get(),
            identities: []
         };

         postData.ranges.forEach((r, i) => {
            postData.ranges[i] = {
               firstTime: Utils.dateFormat(r[0], '-', true),
               lastTime: Utils.dateFormat(r[1], '-', true)
            }
         });

         let operationRoutes = this.Gantt.cache.getAll('operationRoute'),
            i = 0,
            total = operationRoutes.length,
            identity = null,
            operations = null;

         for (; i < total; i++) {
            operations = this.Gantt.cache.getByIndex('operations', 'routeSid', operationRoutes[i].sid);
            identity = {
               operationRouteIdentity: {
                  sid: operationRoutes[i].sid,
                  version: operationRoutes[i].version
               },
               operationIdentities: []
            };
            operations.forEach(operation => {
               identity.operationIdentities.push({
                  sid: operation.sid,
                  version: operation.version
               });
            });
            postData.identities.push(identity);
         }

         Http.post(Config.api.refreshOperation, JSON.stringify(postData), result => {
            this.finishedRefreshData(result);
         });


         // 刷新浇次数据
         let castHeatData = [],
            casts = this.Gantt.cache.getAll('casts'),
            j = 0,
            length = casts.length,
            cIdentity = null,
            heats = null;

         for (; j < length; j++) {
            heats = this.Gantt.cache.getByIndex('heats', 'castSid', casts[j].sid);
            cIdentity = {
               castIdentity: {
                  sid: casts[j].sid,
                  version: casts[j].version
               },
               heatIdentities: []
            };
            heats.forEach(heat => {
               cIdentity.heatIdentities.push({
                  sid: heat.sid,
                  version: heat.version
               });
            });
            castHeatData.push(cIdentity);
         }
         Http.post(Config.api.refreshSchedulable, JSON.stringify(castHeatData), result => {
            this.finishedRefreshCastHeat(result);
         });
      });
   }

   finishedRefreshData(data) {

      if (data.length === 0) {
         return false;
      }

      let i = 0,
         total = data.length,
         operations = null,
         j = 0,
         operationLength = 0,
         changed = [],
         changedStr = [],
         changedSeries = {},
         seriesId = null,
         removeSeries = [],
         needRedraw = false,
         oldOperation = null;

      for (; i < total; i++) {
         let opR = data[i].operationRoute,
         operationCcmFacilityNo = null,
         colorByCcm = null;
         if (opR.routeId && opR.heatSid) {
            this.Gantt.cache.update('operationRoute', opR);
            // 记录需要更新的图表内容
            seriesId = opR.sid;
            changedSeries[seriesId] = {
               series: OperationParser.parseRoute(opR),
               points: {}
            };
            operations = data[i].operations;
            operationLength = operations.length;
            if (operationLength) {
               for (j = 0; j < operationLength; j++) {
                  if (operations[j].operationStat === 'S') {
                     oldOperation = this.Gantt.cache.getById('operations', operations[j].sid)
                     if (oldOperation && oldOperation.operationStat === 'S' && oldOperation.version !== operations[j].version) {
                        changed.push({
                           heat: oldOperation.heatSid,
                           old: [oldOperation.facilityNo, oldOperation.planStartTime],
                           new: [operations[j].facilityNo, operations[j].planStartTime]
                        });
                     }
                  }

                  if(operations[j].facilityNo.substring(0,3) ==='CCM'){
                     operationCcmFacilityNo = operations[j].facilityNo;
                     colorByCcm = OperationParser.getOperationRouteColor(operationCcmFacilityNo);
                  }
                  changedSeries[seriesId].series.color = colorByCcm;

                  this.Gantt.cache.update('operations', operations[j]);
                  changedSeries[seriesId].points[operations[j].sid] = OperationParser.parseOperation(operations[j]);
               }
            }
         } else {
            let operationRoute = this.Gantt.cache.getById('operationRoute', opR.sid);
            let removeHeatSid = operationRoute.heatSid;
            let removeSerie = this.Gantt.chart.searchSeriesByHeatSid([removeHeatSid]);
            if(!Utils.isEmpty(removeSerie)){
               removeSeries = removeSeries.concat(removeSerie);
            }
            this.Gantt.cache.clearMasterSlaveData('operationRoute', 'operations', [opR.Sid], {
               masterObjKey: 'operationRoute',
               masterObjIndex: 'routeSid'
            });
         }

      }

      if (changed && changed.length > 0) {
         i = 0;
         total = changed.length;

         for (i; i < total; i++) {
            let heat = this.Gantt.cache.getById('heats', changed[i].heat);
            changedStr.push('制造命令 ' + heat.taskCounter + ' 变更：' +
               changed[i].old[0] + '/' + changed[i].old[1].substring(11, 16) + ' -> ' +
               changed[i].new[0] + '/' + changed[i].new[1].substring(11, 16)
            );
         }

         this.Gantt.modal.showDataUpdatedModal(changedStr);
      }
      if (removeSeries.length > 0) {
         let needEmptySeries = removeSeries.length === this.Gantt.chart.series.length;
         // 更新图表
         removeSeries.forEach(s => {
            s.remove(false);
         })
         if (needEmptySeries) {
            this.Gantt.chart.addSeries({
               id: 'empty',
               data: []
            }, false);
         }
         needRedraw = true;
      }
      // 更新图表数据
      if (changedSeries && !Utils.isObjEmpty(changedSeries)) {
         let seriesIdKey = null,
            series = null,
            changedSerie = null,
            newSeries = [];
         for (seriesIdKey in changedSeries) {
            series = this.Gantt.chart.get(parseInt(seriesIdKey));
            changedSerie = changedSeries[seriesIdKey];
            if (series) {
               // 更新 series
               series.name = changedSerie.series.name;
               series.options.name = changedSerie.series.name;
               series.options.heatSid = changedSerie.series.heatSid;
               series.options.extra = changedSerie.series.extra;

               let min = Infinity,
                  max = 0,
                  pointNewValue = null;
               series.points.forEach(p => {
                  if (changedSerie.points[p.extra.sid]) {
                     pointNewValue = changedSerie.points[p.extra.sid];
                     p.update(pointNewValue, false);
                     if (pointNewValue.x < min) {
                        min = pointNewValue.x;
                     }
                     if (pointNewValue.x2 > max) {
                        max = pointNewValue.x2;
                     }
                  } else {
                     if (p.x < min) {
                        min = p.x;
                     }
                     if (p.x2 > max) {
                        max = p.x2;
                     }
                  }
               });

               series.options.extra.min = min;
               series.options.extra.max = max;
            } else {
               changedSerie.series.data = []
               for (let key in changedSerie.points) {
                  changedSerie.series.data.push(changedSerie.points[key]);
               }
               let heat = this.Gantt.cache.getById('heats', changedSerie.series.heatSid);
               changedSerie.series.caId = heat.caId;
               this.Gantt.chart.addSeries(changedSerie.series, false);
            }
         }
         needRedraw = true;
      }
      
      if (needRedraw) {
         this.Gantt.chart.redraw();
         this.Gantt.doValidate();
         this.Gantt.chart.currentSelectPoint = null;
         this.Gantt.chart.selectedChange();
      }
   }

   finishedRefreshCastHeat(data) {

      if (data.length === 0) {
         return false;
      }
      // 更新浇次数据
      data.forEach(d => {
         this.Gantt.cache.update('casts', d.cast);
         this.Gantt.cache.updateAll('heats', d.heats);
      });

      this.Gantt.updateCastPlan();
   }
}

export default GanttTimer;